package com.quanyan.user.service.impl;

import com.quanyan.common.constants.Constants;
import com.quanyan.redisCluster.utils.SerializeUtil;
import com.quanyan.user.cache.MyRedisTemplate;
import com.quanyan.user.constants.UserConstants;
import com.quanyan.user.mapper.TbTreasureBoxMapper;
import com.quanyan.user.mapper.TbUserTreasureBoxMapper;
import com.quanyan.user.mapper.UserTreasureBoxMapper;
import com.quanyan.user.model.db.TbTreasureBox;
import com.quanyan.user.model.db.TbTreasureBoxExample;
import com.quanyan.user.model.db.TbUserTreasureBox;
import com.quanyan.user.model.db.TbUserTreasureBoxExample;
import com.quanyan.user.model.vo.response.RespTreasureBox;
import com.quanyan.user.model.vo.response.RespUserCenter;
import com.quanyan.user.model.vo.response.RespUserTreasureBox;
import com.quanyan.user.service.ReceiveDetailService;
import com.quanyan.user.service.UserTreasureBoxService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by Administrator on 2016/7/1.
 */
@Service
public class UserTreasureBoxServiceImpl implements UserTreasureBoxService{

    private static final Logger logger = LoggerFactory.getLogger(UserTreasureBoxServiceImpl.class);

    @Autowired
    private TbTreasureBoxMapper tbTreasureBoxMapper;

    @Autowired
    private UserTreasureBoxMapper userTreasureBoxMapper;

   @Autowired
   private TbUserTreasureBoxMapper tbUserTreasureBoxMapper;

    @Autowired
    private MyRedisTemplate myRedisTemplate;

    @Autowired
    private ReceiveDetailService receiveDetailService;

    @Override
    public void initUserTreasureBox(Integer uid) {
        logger.info("{}注册,初始化用户宝箱---------------》",uid);
        List<TbUserTreasureBox> lst = new ArrayList<TbUserTreasureBox>();
        Map<byte[],byte[]> map = myRedisTemplate.hgetAll(UserConstants.UC_SYS_BOX);
        if(map != null && map.size() >0 ) {
            logger.info("开始从缓存中查找系统宝箱---------------------》");
            for (Map.Entry<byte[], byte[]> entry : map.entrySet()) {
                TbTreasureBox t = (TbTreasureBox)SerializeUtil.unserialize(entry.getValue());
                TbUserTreasureBox tbUserTreasureBox = new TbUserTreasureBox();
                tbUserTreasureBox.setUid(uid);
                tbUserTreasureBox.setIsDelete(Constants.IS_DELETE_FALSE);
                tbUserTreasureBox.setTreasureBoxId(t.getId());
                tbUserTreasureBox.setStatus(UserConstants.BoxStatus.OPEN_FALSE);
                tbUserTreasureBox.setRuleEggShells(t.getRuleEggShells());
                tbUserTreasureBox.setLevel(t.getLevel());
                tbUserTreasureBox.setCreateTime(new Date());
                tbUserTreasureBox.setUpdateTime(new Date());
                lst.add(tbUserTreasureBox);
            }
            logger.info("结束从缓存中查找系统宝箱 result ---------------------》",lst.toString());

        }else {
            logger.info("开始从数据库中查找系统宝箱---------------------》");
            TbTreasureBoxExample example = new TbTreasureBoxExample();
            TbTreasureBoxExample.Criteria criteria = example.createCriteria();
            criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
            List<TbTreasureBox> boxList =  tbTreasureBoxMapper.selectByExample(example);
            for(TbTreasureBox t :boxList){
                TbUserTreasureBox tbUserTreasureBox = new TbUserTreasureBox();
                tbUserTreasureBox.setUid(uid);
                tbUserTreasureBox.setIsDelete(Constants.IS_DELETE_FALSE);
                tbUserTreasureBox.setTreasureBoxId(t.getId());
                tbUserTreasureBox.setStatus(UserConstants.BoxStatus.OPEN_FALSE);
                tbUserTreasureBox.setRuleEggShells(t.getRuleEggShells());
                tbUserTreasureBox.setLevel(t.getLevel());
                tbUserTreasureBox.setCreateTime(new Date());
                tbUserTreasureBox.setUpdateTime(new Date());
                lst.add(tbUserTreasureBox);
            }
            logger.info("结束从数据库中查找系统宝箱 result{} ---------------------》",lst.toString());
        }

        userTreasureBoxMapper.batchInsert(lst);
        logger.info("初始化用户宝箱完毕-------------------------》");

    }


    /**
     * 设置用户宝箱
     * @param uid
     */
    public void setUpUserBox(Integer uid){
        logger.info("----------》开始设置用户宝箱");
        Map<byte [] ,byte []> map = myRedisTemplate.hgetAll(UserConstants.UC_SYS_BOX); //系统箱子
        for (Map.Entry<byte[], byte[]> entry : map.entrySet()){
            TbTreasureBox tbTreasureBox = (TbTreasureBox)SerializeUtil.unserialize(entry.getValue());//系统宝箱
            RespUserTreasureBox respUserTreasureBox = new RespUserTreasureBox();
            respUserTreasureBox.setBoxId(tbTreasureBox.getId());
            respUserTreasureBox.setBoxName(tbTreasureBox.getName());
            respUserTreasureBox.setLevel(tbTreasureBox.getId());
            respUserTreasureBox.setStatus(UserConstants.BoxStatus.OPEN_FALSE);//未打开
            if(tbTreasureBox.getReward() != null)
                respUserTreasureBox.setRewardEggShellNum(new BigDecimal(tbTreasureBox.getReward()));
            if(tbTreasureBox.getRuleEggShells() != null)
                respUserTreasureBox.setRuleEggShellsNum(new BigDecimal(tbTreasureBox.getRuleEggShells()));
            myRedisTemplate.hset(UserConstants.getUserBoxRedisKey(uid),respUserTreasureBox.getBoxId().toString(),respUserTreasureBox);
        }
        myRedisTemplate.setExpire(UserConstants.getUserBoxRedisKey(uid),1);//设置一天失效时间
        logger.info("----------》结束设置用户宝箱");

    }


    /**
     * 获取用户宝箱
     * @param uid
     * @return
     */
    public RespTreasureBox queryUserBox(Integer uid,Long currentDayReceiveEggshellNum){
        logger.info("开始查询用户宝箱：uid;{}",uid);

        RespTreasureBox respBox = new RespTreasureBox();
        if(uid != null){
            String key = UserConstants.getUserBoxRedisKey(uid);
            if(currentDayReceiveEggshellNum == null)
                 currentDayReceiveEggshellNum = receiveDetailService.getCurrentDayReceiveEggShellNum(uid);
            List<RespUserTreasureBox> respUserTreasureBoxArrayList = new ArrayList<RespUserTreasureBox>();
            Map<byte [] ,byte [] > map = myRedisTemplate.hgetAll(key);//获取用户当日宝箱
            if(map == null || map.size() < 1){
                this.setUpUserBox(uid);
                map = myRedisTemplate.hgetAll(key);
            }//当日宝箱不存在

            for (Map.Entry<byte[], byte[]> entry : map.entrySet()) {
                RespUserTreasureBox userBox = (RespUserTreasureBox) SerializeUtil.unserialize(entry.getValue());//系统宝箱
                respUserTreasureBoxArrayList.add(userBox);
            }

            Comparator<RespUserTreasureBox> comparator = new Comparator<RespUserTreasureBox>() {
                @Override
                public int compare(RespUserTreasureBox o1, RespUserTreasureBox o2) {
                    return o1.getLevel().compareTo(o2.getLevel());
                }
            };
            Collections.sort(respUserTreasureBoxArrayList, comparator);
            logger.info("用户当日宝箱--------------------》result:{}",respUserTreasureBoxArrayList.toString());


            List<RespUserTreasureBox> openNoReceiveSet = new ArrayList<RespUserTreasureBox>();//可领取的箱子
            List<RespUserTreasureBox> noOpenSet = new ArrayList<RespUserTreasureBox>();// 没开启的箱子
            List<RespUserTreasureBox> receiveSet = new ArrayList<RespUserTreasureBox>();// 已经领取的箱子

            for (RespUserTreasureBox box :respUserTreasureBoxArrayList){
                if(UserConstants.BoxStatus.OPEN_NO_RECEIVE == box.getStatus()) // 可领取状态
                    openNoReceiveSet.add(box);

                if(UserConstants.BoxStatus.OPEN_FALSE == box.getStatus())//未开启的箱子
                    noOpenSet.add(box);

                if(UserConstants.BoxStatus.OPEN_YES_RECEIVE == box.getStatus())//已经领取的箱子
                    receiveSet.add(box);
            }

            int sysBoxNum = myRedisTemplate.hgetAll(UserConstants.UC_SYS_BOX).size();
            if(sysBoxNum == noOpenSet.size()){ //一个箱子都没开启
                respBox.setIsReceive(1);
                BigDecimal tem =respUserTreasureBoxArrayList.get(0).getRuleEggShellsNum().subtract(new BigDecimal(currentDayReceiveEggshellNum));
                respBox.setRemark("一级宝箱还差"+ tem +"蛋壳可开启");

                RespUserTreasureBox box = new RespUserTreasureBox();
                box.setBoxName(respUserTreasureBoxArrayList.get(0).getBoxName());
                box.setRuleEggShellsNum(respUserTreasureBoxArrayList.get(0).getRuleEggShellsNum());
                respBox.setRespUserTreasureBox(box);
                return respBox;
            }

            if(sysBoxNum == receiveSet.size()){ //箱子都领完
                respBox.setIsReceive(1);
                respBox.setIsComplete(0);//宝箱领完
                respBox.setRemark("今日宝箱领完了");
                respBox.setRespUserTreasureBox(new RespUserTreasureBox());
                return respBox;
            }

            if(openNoReceiveSet.size() == 0 && receiveSet.size() > 0){ //没有可领取的箱子，但是已经领取过箱子
                RespUserTreasureBox box = noOpenSet.get(0);
                respBox.setIsReceive(1);
                respBox.setRemark(box.getLevel() +"级宝箱" + box.getRuleEggShellsNum().subtract(new BigDecimal(currentDayReceiveEggshellNum))+"蛋壳可开启");
                box.setBoxName(box.getLevel() + "级宝箱");
                box.setRuleEggShellsNum(box.getRuleEggShellsNum());
                respBox.setRespUserTreasureBox(box);
                return respBox;

            }

            if (openNoReceiveSet.size() > 0){//有多个可领取的箱子 返回最低级别的箱子
                RespUserTreasureBox box = openNoReceiveSet.get(0);
                respBox.setRespUserTreasureBox(box);
                respBox.setIsReceive(0);
                return respBox;
            }

        }
        logger.info("结束查询用户宝箱，result:{}");
        return respBox;
    }


    @Override
    public RespTreasureBox queryUserBox(Integer uid,RespUserCenter respUserCenter){
        logger.info("开始查询用户宝箱：uid;{}",uid);
        List<RespUserTreasureBox> respUserTreasureBoxArrayList = new ArrayList<RespUserTreasureBox>();

        RespTreasureBox respBox = new RespTreasureBox();

        if(uid != null){
            respUserTreasureBoxArrayList = userTreasureBoxMapper.queryUserBox(uid);
            Comparator<RespUserTreasureBox> comparator = new Comparator<RespUserTreasureBox>() {
                @Override
                public int compare(RespUserTreasureBox o1, RespUserTreasureBox o2) {
                    return o1.getLevel().compareTo(o2.getLevel());
                }
            };
            Collections.sort(respUserTreasureBoxArrayList, comparator);

            List<RespUserTreasureBox> lst = respUserTreasureBoxArrayList;
            List<RespUserTreasureBox> openNoReceiveSet = new ArrayList<RespUserTreasureBox>();//可领取的箱子
            List<RespUserTreasureBox> noOpenSet = new ArrayList<RespUserTreasureBox>();// 没开启的箱子
            List<RespUserTreasureBox> receiveSet = new ArrayList<RespUserTreasureBox>();// 已经领取的箱子

            for (RespUserTreasureBox box :lst){
                if(UserConstants.BoxStatus.OPEN_NO_RECEIVE == box.getStatus().byteValue()) // 可领取状态
                    openNoReceiveSet.add(box);

                if(UserConstants.BoxStatus.OPEN_FALSE == box.getStatus().byteValue())//未开启的箱子
                        noOpenSet.add(box);

                if(UserConstants.BoxStatus.OPEN_YES_RECEIVE == box.getStatus().byteValue())//已经领取的箱子
                    receiveSet.add(box);
            }
            int sysBoxNum = myRedisTemplate.hgetAll(UserConstants.UC_SYS_BOX).size();
            if(sysBoxNum == noOpenSet.size()){ //一个箱子都没开启
                respBox.setIsReceive(1);
                BigDecimal tem =respUserTreasureBoxArrayList.get(0).getRuleEggShellsNum().subtract(respUserCenter.getReceiveEggShellNum());
                respBox.setRemark("一级宝箱还差"+ tem +"蛋壳可开启");
                respUserCenter.setRespTreasureBox(respBox);
                return respBox;
            }

            if(sysBoxNum == receiveSet.size()){ //箱子都领完
                respBox.setIsReceive(1);
                respBox.setRemark("今日宝箱领完了");
                respUserCenter.setRespTreasureBox(respBox);
                return respBox;
            }

            if(openNoReceiveSet.size() == 0 && receiveSet.size() > 0){ //没有可领取的箱子，但是已经领取过箱子
                RespUserTreasureBox box = receiveSet.get(receiveSet.size() + 1);
                respBox.setIsReceive(1);
                respBox.setRemark(box.getLevel() + 1 +"级宝箱"+box.getRuleEggShellsNum().subtract(respUserCenter.getReceiveEggShellNum())+"蛋壳可开启");
                respUserCenter.setRespTreasureBox(respBox);
                return respBox;

            }

            if (openNoReceiveSet.size() > 0){//有多个可领取的箱子 返回最低级别的箱子
                RespUserTreasureBox box = openNoReceiveSet.get(0);
                respBox.setRespUserTreasureBox(box);
                respBox.setIsReceive(0);
                respUserCenter.setRespTreasureBox(respBox);
                return respBox;
            }

        }
        logger.info("结束查询用户宝箱，result:{}",respUserTreasureBoxArrayList.toString());
        return respBox;
    }


    public void initSystemBox(){
        logger.info("开始缓存系统宝箱");
        TbTreasureBoxExample tbTreasureBoxExample =  new TbTreasureBoxExample();
        TbTreasureBoxExample.Criteria criteria = tbTreasureBoxExample.createCriteria();
        criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        List<TbTreasureBox> lst= tbTreasureBoxMapper.selectByExample(tbTreasureBoxExample);
        if(lst == null || lst.size() < 1)
            return;
        for(TbTreasureBox tbTreasureBox :lst){
            myRedisTemplate.hset(UserConstants.UC_SYS_BOX,tbTreasureBox.getId().toString(),tbTreasureBox);
        }
        logger.info("结束缓存系统宝箱");
    }
}
